package au.edu.utas.yu_qiao_group.luckyman.ui.raffleshome;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.SearchView;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import au.edu.utas.yu_qiao_group.luckyman.MainActivity;
import au.edu.utas.yu_qiao_group.luckyman.R;
import au.edu.utas.yu_qiao_group.luckyman.databinding.TicketSellingDialogBindingImpl;
import au.edu.utas.yu_qiao_group.luckyman.db.raffles.RaffleDTO;
import au.edu.utas.yu_qiao_group.luckyman.service.RaffleService;
import au.edu.utas.yu_qiao_group.luckyman.ui.components.ArrayAdapterSearchView;
import au.edu.utas.yu_qiao_group.luckyman.ui.components.SwipeRecyclerView;

public class RafflesHomeFragment extends Fragment {
  private static final String TAG = "RafflesList";
  private static final String KEY_LAYOUT_MANAGER = "layoutManager";
  private static final int SPAN_COUNT = 2;
  protected ArrayList<RaffleDTO> mDataset;
  protected List<RaffleDTO> mFilteredDataset;
  protected String mKeyword = null;

  private SwipeRecyclerView mRecyclerView;
  private SwipeRecyclerView.Adapter mAdapter;

  private ArrayAdapterSearchView mSearchView;
  private FloatingActionButton mFloatingActionButton;
  protected SwipeRecyclerView.LayoutManager mLayoutManager;

  private SharedRaffleViewModel mTargetRaffleVm;

  private enum LayoutManagerType {
    GRID_LAYOUT_MANAGER,
    LINEAR_LAYOUT_MANAGER
  }

  protected LayoutManagerType mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
  ;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    initDataset();
    mTargetRaffleVm = new ViewModelProvider(getActivity()).get(SharedRaffleViewModel.class);
  }

  @Override
  public View onCreateView(@NonNull LayoutInflater inflater,
                           ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_raffles_home, container, false);
    rootView.setTag(TAG);

    if (mKeyword != null || TextUtils.isEmpty(mKeyword) == false) {
      mKeyword = null;
      updateFilteredDataset();
    };
    initRecyclerView(rootView, savedInstanceState);
    refreshRecyclerView();
    return rootView;
  }

  @Override
  public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.search, menu);
    MenuItem searchViewItem = menu.findItem((R.id.app_bar_search));
    mSearchView = (ArrayAdapterSearchView) searchViewItem.getActionView();
    List<String> pureText = mDataset.stream().map(a -> a.getMName()).collect(Collectors.toList());
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_activated_1, pureText);
    mSearchView.setAdapter(adapter);
    mSearchView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        mKeyword = (String) parent.getItemAtPosition(position);
        mSearchView.setText(mKeyword);
        updateFilteredDataset();
        refreshRecyclerView();
      }
    });
    mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
      @Override
      public boolean onClose() {
        // clear mKeyword and refresh list
        if (mKeyword != null || TextUtils.isEmpty(mKeyword) == false) {
          mKeyword = null;
          updateFilteredDataset();
          refreshRecyclerView();
        }
        return false;
      }
    });
  }

  public void initRecyclerView(final View rootView, Bundle savedInstanceState) {
    mRecyclerView = rootView.findViewById(R.id.raffle_list);

    iniFloatingActionButton(rootView, savedInstanceState);

    mLayoutManager = new LinearLayoutManager(getActivity());

    mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;

    if (savedInstanceState != null) {
      // Restore saved layout manager type.
      mCurrentLayoutManagerType = (LayoutManagerType) savedInstanceState
              .getSerializable(KEY_LAYOUT_MANAGER);
    }
    setRecyclerViewLayoutManager(mCurrentLayoutManagerType);
    mRecyclerView.addOnScrollListener(new FloatingButtonScrollListener(new FloatingButtonScrollListener.HideAndShowListener() {
      @Override
      public void hide() {
        mFloatingActionButton.setAlpha((float) 0.3);
      }

      @Override
      public void show() {
        mFloatingActionButton.setAlpha((float) 1.0);
      }
    }));

    mAdapter = new RaffleListViewItemAdapter(mFilteredDataset, mOnStartBtnClick, mOnEditBtnClick, mOnDelBtnClick);
    // Set CustomAdapter as the adapter for RecyclerView.
    mRecyclerView.setAdapter(mAdapter);
  }

  // prepared for LayoutManager switch feature
  public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
    int scrollPosition = 0;

    // If a layout manager has already been set, get current scroll position.
    if (mRecyclerView.getLayoutManager() != null) {
      scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
              .findFirstCompletelyVisibleItemPosition();
    }

    switch (layoutManagerType) {
      case GRID_LAYOUT_MANAGER:
        mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT);
        mCurrentLayoutManagerType = LayoutManagerType.GRID_LAYOUT_MANAGER;
        break;
      default:
        mLayoutManager = new LinearLayoutManager(getActivity());
        mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
    }

    mRecyclerView.setLayoutManager(mLayoutManager);
    mRecyclerView.scrollToPosition(scrollPosition);
  }

  public void iniFloatingActionButton(final View rootView, Bundle savedInstanceState) {
    mFloatingActionButton = (FloatingActionButton) rootView.findViewById(R.id.create_raffle);
    mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        RaffleDTO targetDTO = new RaffleDTO();
        mTargetRaffleVm.setMode(SharedRaffleViewModel.NEW_MODE_KEY);
        Navigation.findNavController(rootView).navigate(R.id.nav_raffle_detail);
      }
    });
  }

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putSerializable(KEY_LAYOUT_MANAGER, mCurrentLayoutManagerType);
    super.onSaveInstanceState(savedInstanceState);
  }

  private void initDataset() {
    MainActivity activity = (MainActivity) getActivity();
    mDataset = RaffleService.retrieveAll(activity.mDb);
    updateFilteredDataset();
  }

  private void updateFilteredDataset () {
    if (mKeyword == null) {
      mFilteredDataset = new ArrayList<RaffleDTO>();
      mFilteredDataset.addAll(mDataset);
    } else {
      mFilteredDataset = mDataset.stream().filter(i -> i.getMName() == mKeyword)
            .collect(Collectors.toList());
    }
  }

  public void refetchDataset() {
    MainActivity activity = (MainActivity) getActivity();
    mDataset = RaffleService.retrieveAll(activity.mDb);
    List<String> pureText = mDataset.stream().map(a -> a.getMName()).collect(Collectors.toList());
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_activated_1, pureText);
    mSearchView.setAdapter(adapter);
    updateFilteredDataset();
    refreshRecyclerView();
  }

  private void refreshRecyclerView () {
    mRecyclerView.setAdapter(new RaffleListViewItemAdapter(mFilteredDataset, mOnStartBtnClick, mOnEditBtnClick, mOnDelBtnClick));
  }

  private View.OnClickListener mOnStartBtnClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      TicketSellingDialogBindingImpl binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.ticket_selling_dialog, null, true);
      binding.setRaffle(mFilteredDataset.get((Integer) v.getTag()));
      TicketSellingDialog dialog = new TicketSellingDialog(getContext(), (MainActivity) getActivity(),0, 0, binding, R.style.DialogTheme);
      // refresh data when tickets sold
      dialog.setOnSubmit(new TicketSellingDialog.onSubmitListener() {
        @Override
        public void onSubmit() {
          refetchDataset();
        }
      });
      dialog.setCancelable(true);
      dialog.show();
    }
  };

  private View.OnClickListener mOnEditBtnClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      RaffleDTO targetDTO = mFilteredDataset.get((Integer) v.getTag());
      mTargetRaffleVm.setMode(SharedRaffleViewModel.EDIT_MODE_KEY, targetDTO);
      Navigation.findNavController(getView()).navigate(R.id.nav_raffle_detail);
    }
  };

  private View.OnClickListener mOnDelBtnClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
      dialog.setMessage("please double confirm your dangerous DELETE action");
      dialog.setPositiveButton("I am sure", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
          RaffleDTO targetDTO = mFilteredDataset.get((Integer) v.getTag());
          MainActivity activity = (MainActivity) getActivity();
          if (RaffleService.delRaffle(activity.mDb, targetDTO)) {
            refetchDataset();
            Toast.makeText(getContext(), "Successfully deleted " + targetDTO.getMName(), Toast.LENGTH_SHORT).show();
          } else {
            Toast.makeText(getContext(), targetDTO.getMName() + " cannot be deleted for tickets sold already!", Toast.LENGTH_SHORT).show();
          }

        }
      });
      dialog.show();
    }
  };
//
//  // debounce text input to avoid onQueryTextChange executed frequently
//  private final Handler debounceHandler = new Handler();
//
//  private SearchView.OnQueryTextListener searchListener = new SearchView.OnQueryTextListener() {
//    @Override
//    public boolean onQueryTextSubmit(String query) {
//      Toast.makeText(getContext(), "submit", Toast.LENGTH_SHORT).show();
//      return true;
//    }
//
//    @Override
//    public boolean onQueryTextChange(String newText) {
//
//      debounceHandler.removeCallbacksAndMessages(null);
//      final Runnable r = new Runnable() {
//        @Override
//        public void run() {
//        }
//      };
//      debounceHandler.postDelayed(r, 500);
//      return true;
//    }
//  };
}
